package com.dingreading.cloud.admin.controller;

import com.dingreading.cloud.admin.dto.StockOutDeliveryDto;
import com.dingreading.cloud.admin.dto.vo.WhStockOutGoodsLogVo;
import com.dingreading.cloud.admin.entity.OrderForm;
import com.dingreading.cloud.admin.entity.WhStockOutGoods;
import com.dingreading.cloud.admin.entity.WhStockOutGoodsLog;
import com.dingreading.cloud.admin.service.*;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.excel.ExcelHandler;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/system/whStockOutGoodsLog")
@Api(tags = "总部-仓库出库商品记录管理")
public class WhStockOutGoodsLogController {

    @Resource
    protected WhStockOutGoodsLogService stockOutGoodsLogService;
    @Resource
    protected WhStockOutGoodsService stockOutGoodsService;
    @Resource
    protected WhStockOutService stockOutService;
    @Resource
    protected OrderFormService orderFormService;
    @Resource
    protected ShopCartService shopCartService;


    @ApiOperation(value = "出库记录分页列表")
    @PostMapping(value = "/pageList", produces = "application/json; charset=UTF-8")
    public R<Object> pageList(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "订单编号/出库单号/采购单号/入库单号/商品名/商品规格名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "出库方式 1.自营仓库 2.线上发货 3.第三方仓库") @RequestParam(value = "stockOutMethod", required = false) Integer stockOutMethod,
            @ApiParam(value = "状态 -1.出库退回 0.已取消 1.出库完成 2.保存") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) {
        Page<WhStockOutGoodsLog> page = stockOutGoodsLogService.pageList(pageUtil, keyword, status, stockOutMethod, beginDate, endDate);

        PageBeanDto data = new PageBeanDto();
        data.setTotal(page.getTotalRow());
        data.setList(page.getRecords());
        return R.ok(data);
    }


    @ApiOperation(value = "导出出库商品记录")
    @PostMapping(value = "/exportList", produces = "application/vnd.ms-excel;charset=UTF-8")
    public void exportList(
            HttpServletResponse response,
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "订单编号/出库单号/采购单号/入库单号/商品名/商品规格名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "出库方式 1.自营仓库 2.线上发货 3.第三方仓库") @RequestParam(value = "stockOutMethod", required = false) Integer stockOutMethod,
            @ApiParam(value = "状态 -1.出库退回 0.已取消 1.出库完成 2.保存") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) throws Exception {
        if (StringUtils.isBlank(beginDate) || StringUtils.isBlank(endDate)) {
            // 获取本月的第一天和最后一天
            Date monthMinDate = DateUtil.getMonthMinDate();
            Date monthMaxDate = DateUtil.getMonthMaxDate();
            beginDate = DateUtil.getDefaultTime2DateStr(monthMinDate);
            endDate = DateUtil.getDefaultTime2DateStr(monthMaxDate);
        }

        List<WhStockOutGoodsLogVo> voList = new ArrayList<>();

        List<WhStockOutGoodsLog> list = stockOutGoodsLogService.getExportList(keyword, status, stockOutMethod, beginDate, endDate);
        if (CollectionUtils.isEmpty(list))
            throw new DescribeException("未查询到数据");

        Set<String> outCodes = new HashSet<>();
        Set<String> orderCodes = new HashSet<>();
        for (WhStockOutGoodsLog goodsLog : list) {
            outCodes.add(goodsLog.getOutCode());
            orderCodes.add(goodsLog.getOrderCode());
        }

        Map<List<Object>, WhStockOutGoods> stockOutGoodsMap = new HashMap<>();
        Map<String, StockOutDeliveryDto> deliveryMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(outCodes)) {
            List<String> outCodeList = new ArrayList<>(outCodes);
            List<WhStockOutGoods> stockOutGoodsList = stockOutGoodsService.listByOutCodes(outCodeList);
            if (CollectionUtils.isNotEmpty(stockOutGoodsList)) {
                //  定义一个函数Function，该函数将元素对象映射到一个键的集合里
                Function<WhStockOutGoods, List<Object>> compositeKey =
                        stockOutGoods -> Arrays.asList(stockOutGoods.getOutCode(), stockOutGoods.getShopCartId());
                // 多字段分组
                stockOutGoodsMap = stockOutGoodsList.stream().collect(Collectors.toMap(compositeKey, Function.identity()));
            }

            List<StockOutDeliveryDto> deliveryDtoList = stockOutService.deliveryListByCodes(outCodeList);
            if (CollectionUtils.isNotEmpty(deliveryDtoList)) {
                deliveryMap = deliveryDtoList.stream().collect(Collectors.toMap(StockOutDeliveryDto::getOutCode, Function.identity()));
            }
        }

        Map<String, OrderForm> orderFormMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(orderCodes)) {
            List<OrderForm> orderFormList = orderFormService.listByCodes(new ArrayList<>(orderCodes));
            if (CollectionUtils.isNotEmpty(orderFormList)) {
                orderFormMap = orderFormList.stream().collect(Collectors.toMap(OrderForm::getCode, Function.identity()));
            }
        }

        for (WhStockOutGoodsLog data : list) {
            WhStockOutGoodsLogVo vo = new WhStockOutGoodsLogVo();
            vo.setOutCode(data.getOutCode());
            vo.setOrderCode(data.getOrderCode());
            vo.setInCode(data.getInCode());
            vo.setPurchaseCode(data.getPurchaseCode());
            vo.setSupplierName(data.getSupplierName());
            vo.setGoodsName(data.getGoodsName());
            vo.setGoodsTypeName(data.getGoodsTypeName());
            vo.setUnit(data.getUnit());
            Integer realStatus = data.getRealStatus();
            if (realStatus != null)
                vo.setRealStatus(data.getRealStatus().equals(1) ? "实体" : "虚拟");
            vo.setNum(data.getNum());

            // 下单人
            OrderForm orderForm = orderFormMap.get(data.getOrderCode());
            if (orderForm != null) {
                vo.setStoreName(orderForm.getStoreName());
                vo.setName(orderForm.getName());
                vo.setAddress(orderForm.getAddress());
            }

            // 获取出库单的商品出库记录
            WhStockOutGoods stockOutGoods = stockOutGoodsMap.get(Arrays.asList(data.getOutCode(), data.getShopCartId()));
            if (stockOutGoods != null) {
                // 出库/销售单价
                Double unitPrice = NepUtil.nullToZero(stockOutGoods.getUnitPrice());
                vo.setUnitPrice(unitPrice);
                // 出库/销售金额
                Double price = NepUtil.nullToZero(stockOutGoods.getPrice());
                vo.setPrice(price);
                // 加权平均价
                Double wetAvgPrice = NepUtil.nullToZero(stockOutGoods.getWetAvgPrice());
                if (wetAvgPrice > 0) {
                    wetAvgPrice = DoubleUtil.round(wetAvgPrice, 2);
                }
                // 成本金额
                vo.setCostPrice(DoubleUtil.mul(data.getNum(), wetAvgPrice));
            }
            // 出库的快递信息
            StockOutDeliveryDto deliveryDto = deliveryMap.get(data.getOutCode());
            if (deliveryDto != null) {
                vo.setExpressName(deliveryDto.getExpressName());
                vo.setExpressCode(deliveryDto.getExpressCode());
                vo.setExpressPrice(deliveryDto.getExpressPrice());
                // 快递费用到付 1.公司支付 2.到付 3.自提
                if (deliveryDto.getExpressPayType() != null) {
                    if (deliveryDto.getExpressPayType().equals(1))
                        vo.setExpressPayType("公司支付");
                    else if (deliveryDto.getExpressPayType().equals(2))
                        vo.setExpressPayType("到付");
                    else
                        vo.setExpressPayType("自提");
                }
                vo.setDeliveryWarehouseName(deliveryDto.getDeliveryWarehouseName());
            }
            vo.setCreator(data.getCreator());
            vo.setRefundName(data.getRefundName());
            vo.setStatusName(data.getStatusName());
            // 出库方式 1.自营仓库 2.线上发货 3.第三方仓库
            if (data.getStockOutMethod() != null) {
                if (data.getStockOutMethod().equals(1))
                    vo.setStockOutMethod("自营仓库");
                else if (data.getStockOutMethod().equals(2))
                    vo.setStockOutMethod("线上发货");
                else if (data.getStockOutMethod().equals(3))
                    vo.setStockOutMethod("第三方仓库");
            }
            if (data.getAddTime() != null)
                vo.setAddTime(DateUtil.getDefaultTimeStr(data.getAddTime()));
            if (data.getRefundTime() != null)
                vo.setRefundTime(DateUtil.getDefaultTimeStr(data.getRefundTime()));

            voList.add(vo);
        }

        String fileName = "出库商品记录" + beginDate + "至" + endDate;
        ExcelHandler.exportExcel(response, voList, WhStockOutGoodsLogVo.class, fileName, "出库商品记录", true);
    }

}